/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.dataset.r3000;

import java.util.*;
import java.io.*;
import java.net.Socket;

import javax.net.SocketFactory;

public class R3000DataClient {

    public static void main(String[] args) {
        int failCount = 0;
        try {
            if (args.length != 2) {
                System.out.println("Usage: java R3000DataClient host built_list");
                return;
            }
            while (true) {

                String host = args[0];

                Vector<String> temp = new Vector<String>();
                LineNumberReader in = new LineNumberReader(new FileReader(args[1]));
                String line = in.readLine();
                while (line != null) {
                    if (line.length() >= 8) {
                        temp.addElement(line);
                    }
                    line = in.readLine();
                }
                in.close();

                R3000Entry[] entries = new R3000Entry[temp.size() + 1];
                for (int i = 0; i < entries.length - 1; i++) {
                    entries[i] = new R3000Entry((String) temp.elementAt(i));
                    // System.out.println(entries[i]);
                }
                // Arrays.sort(entries);

                GregorianCalendar end = (GregorianCalendar) Calendar.getInstance();
                end.set(Calendar.YEAR, 2004);
                end.set(Calendar.MONTH, 0);
                end.set(Calendar.DAY_OF_MONTH, 1);
                String endStr = "20050701";
                String startStr = "20100101";

                GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
                cal.setTimeInMillis(System.currentTimeMillis());
                // cal.set(Calendar.MONTH, 6);
                // cal.set(Calendar.DAY_OF_MONTH, 1);
                // cal.set(Calendar.YEAR, 2006);

                String calStr = "" + cal.get(Calendar.YEAR);
                int month = cal.get(Calendar.MONTH) + 1;
                if (month < 10)
                    calStr += "0";
                calStr += month;
                int day = cal.get(Calendar.DAY_OF_MONTH);
                if (day < 10)
                    calStr += "0";
                calStr += day;
                boolean didSomething = false;
                while (calStr.compareTo(endStr) >= 0) {
                    // while ((calStr.compareTo(endStr) >= 0) &&
                    // (calStr.compareTo(startStr) <= 0)) {
                    // System.out.println("NOW:" + calStr);
                    if (didSomething) {
                        String exec = "sleep 10";
                        System.out.println(exec);
                        Process p = Runtime.getRuntime().exec(exec);
                        p.waitFor();
                        break;
                    }
                    boolean found = false;
                    for (int i = 0; i < entries.length; i++) {
                        if (entries[i] != null) {
                            // System.out.println(entries[i].getDateString() + "
                            // <-> " + calStr);
                            if (entries[i].getDateString().compareTo(calStr) == 0) {
                                // check each run
                                for (int x = 1; x <= 24; x++) {
                                    if ((entries[i].bitMap & (int) Math.pow(2, x)) == (int) (Math.pow(2, x))) {
                                        // System.out.println("Indexed run #" +
                                        // x);
                                    } else {
                                        // System.out.println("Need to index run
                                        // #" + x);
                                        String dir = "/n/r3000/";
                                        File[] files = (new File(dir)).listFiles(new R3000FileFilter(cal, x));
                                        if ((files != null) && (files.length != 0)) {
                                            String filePath = files[0].getAbsolutePath();
                                            int m = entries[i].cal.get(Calendar.MONTH) + 1;
                                            int d = entries[i].cal.get(Calendar.DAY_OF_MONTH);
                                            int y = entries[i].cal.get(Calendar.YEAR);

                                            String exec = "perl dataclient_r3000.pl " + host + ":9097 " + filePath
                                                    + " " + m + "/" + d + "/" + y + " " + x + " ds";
                                            System.out.println(exec);
                                            Process p = Runtime.getRuntime().exec(exec);
                                            int val = p.waitFor();
                                            // int val = processFile(filePath,
                                            // host, entries[i].cal, x);
                                            System.out.println("Processing returned with code " + val);
                                            if (val < 0) {
                                                System.out.println("Failed to process file: '" + filePath + "'");
                                                failCount++;
                                                if (failCount > 10) {
                                                    System.out.println("Exiting due to too many errors.");
                                                    System.exit(1);
                                                }

                                            } else {
                                                didSomething = true;
                                                entries[i].bitMap += (long) Math.pow(2, x);
                                            }
                                        } else {
                                            // System.out.println("No file
                                            // found.");
                                        }
                                        break;
                                    }
                                }
                                found = true;
                                break;
                            }

                        }
                    }
                    if (!found) {
                        // System.out.println("Need to create new Entry for " +
                        // cal.getTime());
                        R3000Entry e = new R3000Entry();
                        // e.cal = new GregorianCalendar();
                        e.cal.setTimeInMillis(cal.getTimeInMillis());
                        entries[entries.length - 1] = e;
                    } else {
                        cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - 1);
                        calStr = "" + cal.get(Calendar.YEAR);
                        month = cal.get(Calendar.MONTH) + 1;
                        if (month < 10)
                            calStr += "0";
                        calStr += month;
                        day = cal.get(Calendar.DAY_OF_MONTH);
                        if (day < 10)
                            calStr += "0";
                        calStr += day;
                        String exec = "sleep 10";
                        // System.out.println(exec);
                        // Process p = Runtime.getRuntime().exec(exec);
                        // p.waitFor();

                    }
                }
                // Arrays.sort(entries);

                PrintWriter out = new PrintWriter(new FileWriter(args[1]));
                for (int i = 0; i < entries.length; i++) {
                    if ((entries[i] != null) && (entries[i].bitMap > 0)) {
                        out.println(entries[i]);
                        // System.out.println(entries[i]);
                    }
                }
                out.close();

            }
        } catch (Exception E) {
            E.printStackTrace();
        }
    }

    private static int processFile(String filePath, String host, GregorianCalendar cal, int run) {
        try {
            SocketFactory sf = SocketFactory.getDefault();
            Socket s = sf.createSocket(host, 9097);
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            DataInputStream dis = new DataInputStream(s.getInputStream());
            dos.writeInt(11); // sensor ID
            dos.writeInt(1); // insert
            dos.writeInt(1); // distributed
            dos.writeInt(1); // self
            dos.writeInt(1);
            dos.writeInt(cal.get(Calendar.MONTH) + 1);
            dos.writeInt(cal.get(Calendar.DAY_OF_MONTH));
            dos.writeInt(cal.get(Calendar.YEAR));
            dos.writeInt(run);

            LineNumberReader in = new LineNumberReader(new FileReader(filePath));
            String line = in.readLine();
            while (line != null) {
                dos.writeInt(line.length());
                dos.writeBytes(line);
                line = in.readLine();
            }
            in.close();
            dos.writeInt(-1);
            return dis.readInt();
        } catch (Exception E) {
            E.printStackTrace();
        }
        return -1;
    }

}
